#include <stdint.h>
#include <stdio.h>
#include "gd32f30x.h"
#include "delay.h"
#include "lcd_drv.h"
#include "RTT_Debug.h"

static void GpioInit(void)
{
	/* 使能RCU相关时钟 */
	rcu_periph_clock_enable(RCU_AF);  
	rcu_periph_clock_enable(RCU_GPIOA);  // 使能GPIOA的时钟
	rcu_periph_clock_enable(RCU_GPIOB);  // 使能GPIOB的时钟
	rcu_periph_clock_enable(RCU_GPIOC);  // 使能GPIOC的时钟

	/*
	*WR---PC0		RS---PC1  
	*CS---PC2		RD---PC3
	*RST--PC8		BK---PA8
	*D0--D15    	PB0--15
	*/
	
	/* 数据总线 */
	gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE);
	gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_MAX, GPIO_PIN_ALL); // D0~D15
	gpio_port_write(GPIOB, 0);

	/* 控制信号 */
	gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_MAX, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_8);
	gpio_bit_set(GPIOC, GPIO_PIN_8);
	gpio_bit_reset(GPIOC, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
	
	/* 背光信号 */
	gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_8);
	gpio_bit_reset(GPIOA, GPIO_PIN_8);

}

#define  LCD_RST_SET()   		gpio_bit_set(GPIOC, GPIO_PIN_8)
#define  LCD_RST_RESET()  		gpio_bit_reset(GPIOC, GPIO_PIN_8) 

#define  LCD_RD_SET()			gpio_bit_set(GPIOC, GPIO_PIN_3) 
#define  LCD_RD_RESET()			gpio_bit_reset(GPIOC, GPIO_PIN_3) 
	 
#define  LCD_CS_SET()    		gpio_bit_set(GPIOC, GPIO_PIN_2) 
#define  LCD_CS_RESET()			gpio_bit_reset(GPIOC, GPIO_PIN_2) 
				
#define  LCD_RS_SET()			gpio_bit_set(GPIOC, GPIO_PIN_1) 
#define  LCD_RS_RESET()			gpio_bit_reset(GPIOC, GPIO_PIN_1) 

#define  LCD_WR_SET()     		gpio_bit_set(GPIOC, GPIO_PIN_0) 
#define  LCD_WR_RESET()   		gpio_bit_reset(GPIOC, GPIO_PIN_0)

#define  LCD_BK_ON()      		gpio_bit_set(GPIOA, GPIO_PIN_8)
#define  LCD_BK_OFF() 	  		gpio_bit_reset(GPIOA, GPIO_PIN_8)

#define  LCD_DATA_WRITE(data)   gpio_port_write(GPIOB, data) 
#define  LCD_DATA_READ()    	gpio_input_port_get(GPIOB)

static __forceinline void LcdSendCmd(uint16_t cmdVal)
{
	LCD_CS_RESET();
	LCD_RS_RESET();
    LCD_RD_SET();
	LCD_DATA_WRITE(cmdVal);
	LCD_WR_RESET();
	LCD_WR_SET();
	LCD_CS_SET();
}

static __forceinline void LcdSendData(uint16_t dataVal)
{
	LCD_CS_RESET();
	LCD_RS_SET();
    //LCD_RD_SET();
	LCD_DATA_WRITE(dataVal);
	LCD_WR_RESET();
	LCD_WR_SET();
	LCD_CS_SET();
}

static __forceinline uint16_t Lcd9327ReadReg(uint16_t addr)
{
	uint16_t data[6];
    
	LcdSendCmd(addr);
	/*SET GPIOB Input*/
	gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_MAX, GPIO_PIN_ALL);

    LCD_CS_RESET();
	LCD_RS_SET();
    for (uint8_t i = 0; i < 6; i++)
    {
        LCD_RD_RESET();
        LCD_RD_SET();
        data[i] = LCD_DATA_READ();
    }
    LCD_CS_SET();
	/*SET GPIOB Output*/
	gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_MAX, GPIO_PIN_ALL);

    return (data[3] << 8) | (data[4] & 0x00FF);
}

#define LCD_ILI9327_ID         		 0x9327

static void Lcd9327Init(void)
{
	LcdSendCmd(0xE9); 
	LcdSendData(0x20); 
    
	LcdSendCmd(0x11); // Exit Sleep 
	DelayNms(5);

	LcdSendCmd(0xD1); // VCOM Control
	LcdSendData(0x00); 
	LcdSendData(0x40); 
	LcdSendData(0x49); 

	LcdSendCmd(0xD0); // Power_Setting
	LcdSendData(0x07);
	LcdSendData(0x01); 
	LcdSendData(0x8A);
//	LcdSendCmd(0x21);      // 针对9327IPS反色屏，和之前的9327屏代码相比，只需要注释这个命令即可
	LcdSendCmd(0x36); // Set_address_mode
	LcdSendData(0x48);

	LcdSendCmd(0x3A); // Set_pixel_format
	LcdSendData(0x55); // 0x55:16bit/pixel,65k;0x66:18bit/pixel,262k;

	LcdSendCmd(0xC1);  // Display_Timing_Setting for Normal/Partial Mode
	LcdSendData(0x10); 
	LcdSendData(0x10); 
	LcdSendData(0x02); 
	LcdSendData(0x02); 

	LcdSendCmd(0xC0); // Set Default Gamma 
	LcdSendData(0x00); 
	LcdSendData(0x35); 
	LcdSendData(0x00); 
	LcdSendData(0x00); 
	LcdSendData(0x01); 
	LcdSendData(0x02); 

	LcdSendCmd(0xC5); // Set frame rate 
	LcdSendData(0x02); 

	//WriteComm(0x21);  //Enter_invert_mode

	LcdSendCmd(0xD2); // power setting 
	LcdSendData(0x01); 
	LcdSendData(0x22); 

	LcdSendCmd(0xC8); // Set Gamma 
	LcdSendData(0x02); 
	LcdSendData(0x77); 
	LcdSendData(0x77); 
	LcdSendData(0x00); 
	LcdSendData(0x00); 
	LcdSendData(0x08); 
	LcdSendData(0x00); 
	LcdSendData(0x00); 
	LcdSendData(0x57); 
	LcdSendData(0x00); 
	LcdSendData(0x08); 
	LcdSendData(0x00); 
	LcdSendData(0x08); 
	LcdSendData(0x80); 
	LcdSendData(0x00); 
	LcdSendCmd(0x29); // display on 
	DelayNms(100);
}

static void LcdInit(void)
{
	LCD_RST_RESET();
	DelayNms(100);
	LCD_RST_SET();
	DelayNms(100);
	uint16_t id;
	
	id = Lcd9327ReadReg(0xEF);	
	if (id != LCD_ILI9327_ID)
	{

		DBG_Error("LCD init error\n");
		return;
	}

	Lcd9327Init();
}

static void LcdSetCursor(LcdArea_t *area)
{
	LcdSendCmd(0x2A);
	LcdSendData(area->x1 >> 8);
	LcdSendData(area->x1 & 0xFF);
	LcdSendData(area->x2 >> 8);
	LcdSendData(area->x2 & 0xFF);
	LcdSendCmd(0x2B);
	LcdSendData(area->y1 >> 8);
	LcdSendData(area->y1 & 0xFF);
	LcdSendData(area->y2 >> 8);
	LcdSendData(area->y2 & 0xFF);
	LcdSendCmd(0x2C);
}

void LcdFillPureColor(LcdArea_t *area, uint16_t color)
{ 
	
    if ((area->x1 > LCD_PIXEL_WIDTH - 1) || (area->x2 > LCD_PIXEL_WIDTH - 1)
		|| (area->y1 > LCD_PIXEL_HEIGHT - 1) || (area->y2 > LCD_PIXEL_HEIGHT - 1))
	{
		return;
	}

	LcdSetCursor(area);
	uint32_t totalPoint = (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1);
	LCD_CS_RESET();
	LCD_RD_SET();
	LCD_RS_SET();
	LCD_DATA_WRITE(color);
	for (uint32_t i = 0; i < totalPoint; i++) 
	{	
		LCD_WR_RESET();
		LCD_WR_SET();
	}
	LCD_CS_SET();
}

void LcdDrvInit(void)
{
	GpioInit();
	LcdInit();	
	LCD_BK_ON();
	LcdArea_t area = {0, 0, LCD_PIXEL_WIDTH - 1, LCD_PIXEL_HEIGHT - 1};
	LcdFillPureColor(&area, BLACK);
}

void LcdDrawChar(uint16_t x, uint16_t y, uint8_t ascii, uint16_t textColor, uint16_t bkColor, AsciiFontDesc_t *font)
{
	uint8_t *bitmap;
	LcdArea_t area;
	uint8_t data;
	uint16_t i, j, k;
	
	if (!font->isJustNum)
	{
		bitmap = (uint8_t *)font->bitmap + (ascii - ' ') * font->charHasBytes;
	}
	else
	{
		bitmap = (uint8_t *)font->bitmap + (ascii - '0') * font->charHasBytes;
	}
	
	area.x1 = x;
	area.y1 = y;
	area.x2 = x + (font->width - 1);
	area.y2 = y + (font->height - 1);
	LcdSetCursor(&area);
	
	for (i = 0; i < font->height; i++)
	{
		for (j = 0; j < font->width / 8; j++)
		{
			data = *(bitmap++);
			for (k = 0; k < 8; k++)
			{
				if (data & 0x80)
				{
					LcdSendData(textColor);
				}
				else
				{
					LcdSendData(bkColor);
				}
				data <<= 1;
			}			
		}
		if (font->width % 8 == 0)
		{
			continue;
		}
		data = *(bitmap++);
		for (k = 0; k < font->width % 8; k++)
		{
			if (data & 0x80)
			{
				LcdSendData(textColor);
			}
			else
			{
				LcdSendData(bkColor);
			}
			data <<= 1;
		}
	}	
}

void LcdDrawString(uint16_t x, uint16_t y, char *str, uint16_t textColor, uint16_t bkColor, AsciiFontDesc_t *font)
{
	uint8_t i = 0;
	
	while (*str != '\0')
	{
		LcdDrawChar(x + (i * font->width), y, *str, textColor, bkColor, font);	
		str++;
		i++;
	}
}

void LcdDrawChinese(uint16_t x, uint16_t y, uint16_t textColor, uint16_t bkColor, ChineseFontDesc_t *font)
{
	uint8_t *bitmap;
	LcdArea_t area;
	uint8_t data;
	uint16_t i, j, k, m;

	bitmap = (uint8_t *)font->bitmap;
	
	for (i = 0; i < font->charNums; i++)
	{
		area.x1 = x + (i * font->width);
		area.y1 = y;
		area.x2 = area.x1 + (font->width - 1);
		area.y2 = y + (font->height - 1);
		LcdSetCursor(&area);
		for (j = 0; j < font->height; j++)
		{
			for (k = 0; k < font->width / 8; k++)
			{
				data = *(bitmap++);
				for (m = 0; m < 8; m++)
				{
					if (data & 0x80)
					{
						LcdSendData(textColor);
					}
					else
					{
						LcdSendData(bkColor);
					}
					data <<= 1;
				}			
			}
			if (font->width % 8 == 0)
			{
				continue;
			}
			data = *(bitmap++);
			for (m = 0; m < font->width % 8; m++)
			{
				if (data & 0x80)
				{
					LcdSendData(textColor);
				}
				else
				{
					LcdSendData(bkColor);
				}
				data <<= 1;
			}
		}
	}
}
//void LcdDrawPicture(uint16_t x, uint16_t y, uint16_t pictureColor, uint16_t bkColor, PictureDesc_t *picDesc)
//{
//	uint8_t *picture;
//	uint8_t data;
//	LcdArea_t area;
//	uint16_t i, j, k;
//	
//	picture = (uint8_t *)picDesc->picture;
//	data = *picture;
//	area.x1 = x;
//	area.y1 = y;
//	area.x2 = x + (picDesc->width - 1);
//	area.y2 = y + (picDesc->height - 1);
//	LcdSetCursor(&area);

//	for (i = 0; i < picDesc->height; i++)
//	{
//		for (j = 0; j < picDesc->width / 8; j++)
//		{
//			data = *(picture++);
//			for (k = 0; k < 8; k++)
//			{
//				if (data & 0x80)
//				{
//					LcdSendData(pictureColor);
//				}
//				else
//				{
//					LcdSendData(bkColor);
//				}
//				data <<= 1;
//			}			
//		}
//		if (picDesc->width % 8 == 0)
//		{
//			continue;
//		}
//		data = *(picture++);
//		for (k = 0; k < picDesc->width % 8; k++)
//		{
//			if (data & 0x80)
//			{
//				LcdSendData(pictureColor);
//			}
//			else
//			{
//				LcdSendData(bkColor);
//			}
//			data <<= 1;
//		}		
//	}	
//}

/**
***********************************************************
* @brief 清屏函数
* @param color,要清屏的填充色
* @return 
***********************************************************
*/
void LcdClear(uint16_t color)
{
	LcdArea_t area = {0, 0, LCD_PIXEL_WIDTH - 1, LCD_PIXEL_HEIGHT - 1};
	LcdFillPureColor(&area, color);  
}

void TurnOnScreen(void)
{
	LCD_BK_ON();
}

void TurnOffScreen(void)
{
	LCD_BK_OFF();
}



#if 0
#include <stdint.h>
#include <stdio.h>
#include "gd32f30x.h"
#include "delay.h"
#include "lcd_drv.h"
#include "fonts.h"
#include "RTT_Debug.h"

static void GpioInit(void)
{
	/* 使能RCU相关时钟 */
	rcu_periph_clock_enable(RCU_GPIOD);  //使能GPIOD的时钟
	rcu_periph_clock_enable(RCU_GPIOE);  //使能GPIOE的时钟
	rcu_periph_clock_enable(RCU_GPIOF);  //使能GPIOF的时钟
	rcu_periph_clock_enable(RCU_GPIOG);  //使能GPIOG的时钟

	/* 地址总线 */
	gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0 ); //A0
	gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1 ); //A1
	gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2 ); //A2
	gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_3 ); //A3
	gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_4 ); //A4
	gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_5 ); //A5
	gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); //A6
	gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); //A7
	gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_14); //A8
	gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_15); //A9
	gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0 ); //A10
	gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1 ); //A11
	gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2 ); //A12
	gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_3 ); //A13
	gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_4 ); //A14
	gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_5 ); //A15
	gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_11); //A16
	gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); //A17
	gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); //A18

	/* 数据总线 */
	gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_14); //A0
	gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_15); //A1
	gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0 ); //A2
	gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1 ); //A3
	gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_7 ); //A4
	gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_8 ); //A5
	gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_9 ); //A6
	gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_10); //A7
	gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_11); //A8
	gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); //A9
	gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); //A10
	gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_14); //A11
	gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_15); //A12
	gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_8 ); //A13
	gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_9 ); //A14
	gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_10); //A15

	/* 控制信号 */
	gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_9); //EXMC_NE1
	gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_4); //EXMC_NOE
	gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_5); //EXMC_NWE
}

static void ExmcLcdInit(void)
{
	exmc_norsram_parameter_struct lcdInitStruct;
//	exmc_norsram_struct_para_init(&lcdInitStruct);
	/* 使能EXMC时钟 */
	rcu_periph_clock_enable(RCU_EXMC);

	/* 读时序配置 */
	exmc_norsram_timing_parameter_struct lcdReadTimingInitStruct;
	lcdReadTimingInitStruct.asyn_access_mode = EXMC_ACCESS_MODE_A; //模式A，异步访问SRAM
	lcdReadTimingInitStruct.asyn_address_setuptime = 0;  //异步访问地址建立时间
	lcdReadTimingInitStruct.asyn_address_holdtime  = 0;  //异步访问地址保持时间
	lcdReadTimingInitStruct.asyn_data_setuptime    = 15; //异步访问数据建立时间
	lcdReadTimingInitStruct.bus_latency            = 0;  //同步/异步访问总线延时时间
	lcdReadTimingInitStruct.syn_clk_division       = 0;  //同步访问时钟分频系数（从HCLK中分频）
	lcdReadTimingInitStruct.syn_data_latency       = 0;  //同步访问中获得第1个数据所需要的等待延迟

	/* 写时序配置 */
	exmc_norsram_timing_parameter_struct lcdWriteTimingInitStruct;
	lcdWriteTimingInitStruct.asyn_access_mode = EXMC_ACCESS_MODE_A; //模式A，异步访问SRAM
	lcdWriteTimingInitStruct.asyn_address_setuptime     = 0; //异步访问地址建立时间
	lcdWriteTimingInitStruct.asyn_address_holdtime      = 0; //异步访问地址保持时间
	lcdWriteTimingInitStruct.asyn_data_setuptime        = 2; //异步访问数据建立时间
	lcdWriteTimingInitStruct.bus_latency                = 0; //同步/异步访问总线延时时间
	lcdWriteTimingInitStruct.syn_clk_division           = 0; //同步访问时钟分频系数（从HCLK中分频）
	lcdWriteTimingInitStruct.syn_data_latency           = 0; //同步访问中获得第1个数据所需要的等待延迟

	
	/* Region1配置 */

	lcdInitStruct.norsram_region    = EXMC_BANK0_NORSRAM_REGION1; //Region1
	lcdInitStruct.address_data_mux  = DISABLE;                    //禁用地址、数据总线多路复用
	lcdInitStruct.memory_type       = EXMC_MEMORY_TYPE_SRAM;      //储存器类型为SRAM
	lcdInitStruct.databus_width     = EXMC_NOR_DATABUS_WIDTH_16B; //数据宽度16位
	lcdInitStruct.burst_mode        = DISABLE;                    //禁用突发访问
	lcdInitStruct.wrap_burst_mode   = DISABLE;                    //禁用包突发访问
	lcdInitStruct.asyn_wait         = DISABLE;                    //禁用异步等待
	lcdInitStruct.extended_mode     = ENABLE;                     //使能扩展模式
	lcdInitStruct.memory_write      = ENABLE;                     //使能写入外部存储器
	lcdInitStruct.nwait_signal      = DISABLE;                    //禁用等待输入信号
	lcdInitStruct.write_mode        = EXMC_ASYN_WRITE;            //写入模式为异步写入
	lcdInitStruct.read_write_timing = &lcdReadTimingInitStruct;   //读时序配置
	lcdInitStruct.write_timing      = &lcdWriteTimingInitStruct;  //写时序配置
	lcdInitStruct.nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
    lcdInitStruct.nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
	
	exmc_norsram_init(&lcdInitStruct);
	exmc_norsram_enable(EXMC_BANK0_NORSRAM_REGION1);
}


#define LCD_PIXEL_WIDTH      320
#define LCD_PIXEL_HEIGHT     480
#define LCD_ID         		 0x9488
#define LCD_X_CMD            0x2A
#define LCD_Y_CMD            0x2B
#define LCD_WG_CMD           0x2C


#define LcdSendCmd(cmdVal) 		(*(volatile uint16_t *)0x64000000) = cmdVal      // 发送命令 	
#define LcdSendData(dataVal) 	(*(volatile uint16_t *)0x64000002) = dataVal     // 发送数据
#define LcdGetData() 			(*(volatile uint16_t *)0x64000002)               // 读取数据

#define LCD_BACKLIGHT_ON 	gpio_bit_set(GPIOA, GPIO_PIN_1)
#define LCD_BACKLIGHT_OFF  	gpio_bit_reset(GPIOA, GPIO_PIN_1)

static void BacklightInit(void)
{
	rcu_periph_clock_enable(RCU_GPIOA);
	gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_1);
}

static void LcdInit(void)
{
	uint16_t id;
	LcdSendCmd(0xD3);				   
	id = LcdGetData();	    // dummy read 	
	id = LcdGetData();	    // 读到0X00
	id = LcdGetData();   	// 读取94								   
	id <<= 8;
	id |= LcdGetData();  	// 读取88	 
	DBG_log("LCD ID:%x\n", id); 
	
	if (id != LCD_ID)
	{
		DBG_log("LCD init error\n");
		return;
	}

	LcdSendCmd(0XF7);
	LcdSendData(0xA9);
	LcdSendData(0x51);
	LcdSendData(0x2C);
	LcdSendData(0x82);
	LcdSendCmd(0xC0);
	LcdSendData(0x11);
	LcdSendData(0x09);
	LcdSendCmd(0xC1);
	LcdSendData(0x41);
	LcdSendCmd(0XC5);
	LcdSendData(0x00);
	LcdSendData(0x0A);
	LcdSendData(0x80);
	LcdSendCmd(0xB1);
	LcdSendData(0xB0);
	LcdSendData(0x11);
	LcdSendCmd(0xB4);
	LcdSendData(0x02);
	LcdSendCmd(0xB6);
	LcdSendData(0x02);
	LcdSendData(0x22);
	LcdSendCmd(0xB7);
	LcdSendData(0xc6);
	LcdSendCmd(0xBE);
	LcdSendData(0x00);
	LcdSendData(0x04);
	LcdSendCmd(0xE9);
	LcdSendData(0x00);
	LcdSendCmd(0x36);
	LcdSendData(0x08);
	LcdSendCmd(0x3A);
	LcdSendData(0x55);
	LcdSendCmd(0xE0);
	LcdSendData(0x00);
	LcdSendData(0x07);
	LcdSendData(0x10);
	LcdSendData(0x09);
	LcdSendData(0x17);
	LcdSendData(0x0B);
	LcdSendData(0x41);
	LcdSendData(0x89);
	LcdSendData(0x4B);
	LcdSendData(0x0A);
	LcdSendData(0x0C);
	LcdSendData(0x0E);
	LcdSendData(0x18);
	LcdSendData(0x1B);
	LcdSendData(0x0F);
	LcdSendCmd(0XE1);
	LcdSendData(0x00);
	LcdSendData(0x17);
	LcdSendData(0x1A);
	LcdSendData(0x04);
	LcdSendData(0x0E);
	LcdSendData(0x06);
	LcdSendData(0x2F);
	LcdSendData(0x45);
	LcdSendData(0x43);
	LcdSendData(0x02);
	LcdSendData(0x0A);
	LcdSendData(0x09);
	LcdSendData(0x32);
	LcdSendData(0x36);
	LcdSendData(0x0F);
	LcdSendCmd(0x11);
	LcdSendCmd(0x29);	
}

void LcdDrvInit(void)
{
	GpioInit();
	ExmcLcdInit();
	BacklightInit();
	LcdInit();
	LcdClear(WHITE);
	LCD_BACKLIGHT_ON;
}
static void LcdSetCursor(LcdArea_t *area)
{
	LcdSendCmd(LCD_X_CMD);  // 发送x cmd
	LcdSendData(area->x1 >> 8);
	LcdSendData(area->x1 & 0XFF); 
	LcdSendData(area->x2 >> 8);
	LcdSendData(area->x2 & 0XFF);
	LcdSendCmd(LCD_Y_CMD);  // 发送y cmd
	LcdSendData(area->y1 >> 8);
	LcdSendData(area->y1 & 0XFF);
	LcdSendData(area->y2 >> 8);
	LcdSendData(area->y2 & 0XFF);	
	LcdSendCmd(LCD_WG_CMD);            // 开始写入GRAM
}
//static void LcdSetCursor(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey)
//{
//	LcdSendCmd(LCD_X_CMD);  // 发送x cmd
//	LcdSendData(sx >> 8);
//	LcdSendData(sx & 0XFF); 
//	LcdSendData(ex >> 8);
//	LcdSendData(ex & 0XFF);
//	LcdSendCmd(LCD_Y_CMD);  // 发送y cmd
//	LcdSendData(sy >> 8);
//	LcdSendData(sy & 0XFF);
//	LcdSendData(ey >> 8);
//	LcdSendData(ey & 0XFF);
//}

/**
***********************************************************
* @brief 在指定区域内填充单个颜色
* @param (sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:
		 (ex-sx+1)*(ey-sy+1)，color:要填充的颜色
* @return 
***********************************************************
*/
void LcdFillPureColor(LcdArea_t *area, uint16_t color)
{
	uint32_t totalPoint = (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1); // 得到总点数    
	LcdSetCursor(area);      // 设置显示区域
	
	for (uint32_t i = 0; i < totalPoint; i++)
	{
		LcdSendData(color);
	}	
}
//void LcdFillPureColor(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color)
//{
//	
//	uint32_t totalPoint = (ex - sx + 1) * (ey - sy + 1); // 得到总点数    
//	LcdSetCursor(sx, sy, ex, ey);      // 设置显示区域
//	LcdSendCmd(LCD_WG_CMD);            // 开始写入GRAM
//	for (uint32_t i = 0; i < totalPoint; i++)
//	{
//		LcdSendData(color);
//	}
//}

/**
***********************************************************
* @brief 清屏函数
* @param color,要清屏的填充色
* @return 
***********************************************************
*/
void LcdClear(uint16_t color)
{
	LcdArea_t area = {0, 0, LCD_PIXEL_WIDTH - 1, LCD_PIXEL_HEIGHT - 1};
	LcdFillPureColor(&area, color);  
}

void LcdDrawChar(uint16_t x, uint16_t y, uint8_t ascii, uint16_t textColor, uint16_t bkColor, AsciiFontDesc_t *font)
{
	uint8_t *bitmap;
	LcdArea_t area;
	uint8_t data;
	uint16_t i, j, k;
	
	if (!font->isJustNum)
	{
		bitmap = (uint8_t *)font->bitmap + (ascii - ' ') * font->charHasBytes;
	}
	else
	{
		bitmap = (uint8_t *)font->bitmap + (ascii - '0') * font->charHasBytes;
	}
	
	area.x1 = x;
	area.y1 = y;
	area.x2 = x + (font->width - 1);
	area.y2 = y + (font->height - 1);
	LcdSetCursor(&area);
	
	for (i = 0; i < font->height; i++)
	{
		for (j = 0; j < font->width / 8; j++)
		{
			data = *(bitmap++);
			for (k = 0; k < 8; k++)
			{
				if (data & 0x80)
				{
					LcdSendData(textColor);
				}
				else
				{
					LcdSendData(bkColor);
				}
				data <<= 1;
			}			
		}
		if (font->width % 8 == 0)
		{
			continue;
		}
		data = *(bitmap++);
		for (k = 0; k < font->width % 8; k++)
		{
			if (data & 0x80)
			{
				LcdSendData(textColor);
			}
			else
			{
				LcdSendData(bkColor);
			}
			data <<= 1;
		}
	}	
}

void LcdDrawString(uint16_t x, uint16_t y, char *str, uint16_t textColor, uint16_t bkColor, AsciiFontDesc_t *font)
{
	uint8_t i = 0;
	
	while (*str != '\0')
	{
		LcdDrawChar(x + (i * font->width), y, *str, textColor, bkColor, font);	
		str++;
		i++;
	}
}

void LcdDrawChinese(uint16_t x, uint16_t y, uint16_t textColor, uint16_t bkColor, ChineseFontDesc_t *font)
{
	uint8_t *bitmap;
	LcdArea_t area;
	uint8_t data;
	uint16_t i, j, k, m;

	bitmap = (uint8_t *)font->bitmap;
	
	for (i = 0; i < font->charNums; i++)
	{
		area.x1 = x + (i * font->width);
		area.y1 = y;
		area.x2 = area.x1 + (font->width - 1);
		area.y2 = y + (font->height - 1);
		LcdSetCursor(&area);
		for (j = 0; j < font->height; j++)
		{
			for (k = 0; k < font->width / 8; k++)
			{
				data = *(bitmap++);
				for (m = 0; m < 8; m++)
				{
					if (data & 0x80)
					{
						LcdSendData(textColor);
					}
					else
					{
						LcdSendData(bkColor);
					}
					data <<= 1;
				}			
			}
			if (font->width % 8 == 0)
			{
				continue;
			}
			data = *(bitmap++);
			for (m = 0; m < font->width % 8; m++)
			{
				if (data & 0x80)
				{
					LcdSendData(textColor);
				}
				else
				{
					LcdSendData(bkColor);
				}
				data <<= 1;
			}
		}
	}
}
#endif

